package cc.telecomdigital.tdstock.trading.Services;

import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;

import cc.telecomdigital.tdstock.R;
import cc.telecomdigital.tdstock.Framework.UniqueItem.DeviceInfo;
import cc.telecomdigital.tdstock.Framework.UniqueItem.TDStockLog;
import cc.telecomdigital.tdstock.Services.SoapTransport;
import cc.telecomdigital.tdstock.trading.Common.Trade_AppConstant;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

public class TradeLogin
{	
	private final String	LOG_TAG	= "TradeLogin";

	// Call back interface
	public interface ITradeLoginResponse
	{		
		/** if iSuccessfulSend == false, it means the there is a communication error
		    do not consider the iReponse as valid response **/
		void ResponseFunc(boolean iSuccessfulSend, TradeLoginResult iResponse);
	}

	// Response Result
	public class TradeLoginResult
	{
		public boolean	Result;
		public String	StatusCode;
		public String	BrokerMessage;
		public String	UsrMessage;

		/**		    
		 * @param iResult - being sent or not
		 * @param iStatusCode - return code from server
		 * @param iBrokerMessage - broker message for successful sent
		 * @param iUsrMessage - user message for successful sent 
		 **/			
		public TradeLoginResult(boolean iResult, String iStatusCode,
				String iBrokerMessage, String iUsrMessage)
		{
			Result = iResult;
			StatusCode = iStatusCode;
			BrokerMessage = iBrokerMessage;
			UsrMessage = iUsrMessage;
		}
	}

	private final boolean debugMode = false;
	private SoapObject	soapRequest;
	private Context	callerContext;
	private boolean	demoData	= false;
	private Handler	messageHandler;

	/** Requesting for a Login
	 * @param iContext - Owner
	 * @param iName - Server required userName
	 * @param iPassword - Server required password
	**/		
	public TradeLogin(Context iCallerContext, String iName, String iPassword)
	{
		callerContext = iCallerContext;
		TradeAppInfo.ResetAllInfo();
		soapRequest = new SoapObject(TradeAppInfo.NAMESPACE, "Login");
		
		soapRequest.addProperty("DeviceID",
				TradeAppInfo.GetDeviceID(iCallerContext));
		soapRequest.addProperty("UIN", TradeAppInfo.GetUIN());
		soapRequest.addProperty("ProtocolVer",
				TradeAppInfo.GetProtocolVersion());
		soapRequest.addProperty("ProgramVer",
				TradeAppInfo.GetProgramVersion());
		soapRequest.addProperty("OSVer", TradeAppInfo.GetOSVersion());
		soapRequest.addProperty("DeviceVer", TradeAppInfo.GetDeviceVer());
		soapRequest.addProperty("BrokerID", TradeAppInfo.BrokerID);
		soapRequest.addProperty("ClientID", iName);
		soapRequest.addProperty("ClientPassword", iPassword);
		soapRequest.addProperty("Language", DeviceInfo.GetLanguageString());
	}

	public void Dispose()
	{		
		messageHandler = null;
		if (debugMode)
			TDStockLog.i(LOG_TAG, "We have no reference anymore");	
	}
	
	private ITradeLoginResponse	responseHandler;

	/** If we are running a demo version, the iUseDemoData could be a fake send **/
	public void SendRequest(boolean iUseDemoData,
			ITradeLoginResponse iTradingLoginResponse)
	{
		demoData = iUseDemoData;
		responseHandler = iTradingLoginResponse;
		messageHandler = new Handler()
		{
			@Override
			public void handleMessage(Message msg)
			{
				if (responseHandler == null)
					return;

				switch (msg.what)
				{
					case REQUEST_DATA_SENT_FAIL:
						responseHandler.ResponseFunc(false, null);
						break;

					case REQUEST_DATA_SENT_SUCCESS:
						responseHandler.ResponseFunc(true,
								(TradeLoginResult) msg.obj);
						break;
				}
			}
		};
		// Start the Thread
		Thread internalThread = new Thread()
		{
			// On purpose pass in to a message handler, so the thread can sleep or be
			// killed
			@Override
			public void run()
			{
				Message msg;
				TradeLoginResult infoData;

				// Provide success or fail reply
				msg = new Message();
				infoData = SendData(demoData);
				if ((infoData.Result == false)
						|| (infoData.StatusCode == null)
						|| (infoData.StatusCode.length() == 0))
					msg.what = REQUEST_DATA_SENT_FAIL;
				else
				{
					msg.what = REQUEST_DATA_SENT_SUCCESS;
					msg.obj = infoData;
				}
				messageHandler.sendMessage(msg);
			}
		};
		internalThread.setName(LOG_TAG);
		internalThread.start();
	}

	private final int	REQUEST_DATA_SENT_FAIL		= 0;
	private final int	REQUEST_DATA_SENT_SUCCESS	= 1;
	
	// iProcess is for real sending or just a reply
	// This is the decoder part
	private TradeLoginResult SendData(boolean iUseDemoData)
	{
		//Prevent for multiple call for network
		synchronized(TradeAppInfo.padLock)
		{		
			TradeLoginResult resultCode;
			SoapSerializationEnvelope envelope;
		
			String statusCode;
			String brokerMsg;
			String usrMessage;
			String serviceStuff;
			String[] tmpString;
	
			if (iUseDemoData == true)
			{
				try
				{
					Thread.sleep(Trade_AppConstant.demoHoldTime);
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
					TDStockLog.e(LOG_TAG, "SendData=>Exception: " + e.toString());
				}
				if (debugMode)
					TDStockLog.i(LOG_TAG, "Using Prepared Data");
				resultCode = new TradeLoginResult(true, "1", null, null);
				return resultCode;
			}
	
			if (DeviceInfo.IsNetworkAvailable(callerContext) == false)
			{
				resultCode = new TradeLoginResult(false, null, null, null);
				return resultCode;
			}
	
			envelope = new SoapSerializationEnvelope(TradeAppInfo.SOAP_VERSION);	
			// Set packet ID
			soapRequest.addProperty("SeqNo", TradeAppInfo.GetSeqNo(true));
			// Last modification of the time
			soapRequest.addProperty("Timestamp",
					TradeAppInfo.GetCurrentTimeStamp());
			envelope.setOutputSoapObject(soapRequest);
					
			statusCode = "0";
			brokerMsg = null;
			usrMessage = null;
			serviceStuff = null;
	
			try
			{			
				SoapObject resultsRequestSOAP;
				SoapObject soapResults;
	
				SoapTransport dataTransfer;
				String        urlString;			
				
				urlString = TradeAppInfo.GetURLAddress(TradeAppInfo.useSSLSetting);
				if (debugMode)
					TDStockLog.i(LOG_TAG, "URL: " + urlString);
				
				if (TradeAppInfo.useSSLSetting)
					dataTransfer = new SoapTransport( callerContext, urlString, 
						   				    		TradeAppInfo.SOAP_COMMUNIC_Timeout, R.raw.ca_stock);
				else
					dataTransfer = new SoapTransport( callerContext, urlString, 
										   		TradeAppInfo.SOAP_COMMUNIC_Timeout);
							
				if (debugMode)
					TDStockLog.i(LOG_TAG, "Try sending Data");
				
				dataTransfer.SendData(TradeAppInfo.SOAP_SERVICENAME, envelope);
							
				resultsRequestSOAP = (SoapObject) envelope.bodyIn;
				if (debugMode)
					TDStockLog.i(LOG_TAG, "Parsing Data");
				
				soapResults = (SoapObject) resultsRequestSOAP
						.getProperty("LoginResult");
	
				serviceStuff = TradeAppInfo.GetSoapProperty(soapResults,
						LOG_TAG, "Services");
				statusCode = TradeAppInfo.GetSoapProperty(soapResults, LOG_TAG,
						"StatusCode");
				brokerMsg = TradeAppInfo.GetSoapProperty(soapResults, LOG_TAG,
						"BrokerMessage");
				usrMessage = TradeAppInfo.GetSoapProperty(soapResults, LOG_TAG,
						"UsrMessage");
			}
			catch (java.net.SocketTimeoutException exTimeout)
			{
				exTimeout.printStackTrace();
				TDStockLog.e(LOG_TAG, "Timeout: " + exTimeout.toString());
				resultCode = new TradeLoginResult(false, null, null, null);
				return resultCode;
			}
			catch (Exception e)
			{
				e.printStackTrace();
				TDStockLog.e(LOG_TAG, e.toString());
				resultCode = new TradeLoginResult(false, null, null, null);
				return resultCode;
			}
	
			resultCode = new TradeLoginResult(true, statusCode, brokerMsg,
					usrMessage);
			// 1 is login success, 2 is login fail
			// If success we will save the session key for future use
			if (statusCode.equals("1") && (serviceStuff != null))
			{
				// First part is the expiration time, 10 digital time in second
				// second part is the session Key
				tmpString = serviceStuff.split(",");
				TradeAppInfo.SetSessionInfo(tmpString[0], tmpString[1]);
			}
			return resultCode;
		}
	}
}